#!/usr/bin/env perl

use strict;
use warnings;
use LWP;
use HTML::TreeBuilder;
use HTML::Element;
use utf8;

package main;

sub fixTimes;

my (
	@urls,
	$userAgent,
	$httpRequest,
	$httpResponse,
	$lineName,
	$lineDesc,
	$repeatRule,
	$stopName,
	$stopDesc,
	$departTime,
	$sep,
	$file,
	@stops,
	@descs,
	@times,
	$colNo,
	$rowNo,
	@lines
);

@urls = (
	"http://taps.ucmerced.edu/cattracks/ab-line",			# ab-line
	"http://taps.ucmerced.edu/cattracks/c1-blue-line",		# c1-blue-line
	"http://taps.ucmerced.edu/cattracks/c1-gold-line",		# c1-gold-line
	"http://taps.ucmerced.edu/cattracks/c2-line",			# c2-lynx-line
	"http://taps.ucmerced.edu/node/250",					# c2-express-line
	"http://taps.ucmerced.edu/cattracks/e-line-m-f",		# e-line-m-f
	"http://taps.ucmerced.edu/cattracks/e1-line-sat-sun",	# e1-line-sat-sun
	"http://taps.ucmerced.edu/node/252",					# e2-line-mid-sat
	"http://taps.ucmerced.edu/cattracks/f-fastcat-line",	# f-fastcat-line
	"http://taps.ucmerced.edu/cattracks/nitecat-line",		# nitecat-line
);

$sep = "|";
@lines = ();

# Allocate user-agent
$userAgent = LWP::UserAgent->new();

$file = "cattracks.csv";
my ($writeHandle);

open($writeHandle, ">$file") or die("Error: can not open $file: $!\n");
print $writeHandle "Line${sep}Line Description${sep}Mo${sep}Tu${sep}We${sep}Th${sep}Fr${sep}Sa${sep}Su${sep}Stop Name${sep}Stop Description${sep}Departure Time${sep}Sequence Number${sep}Number of Stops${sep}Number of Runs\n";
foreach my $url (@urls) {
	$stopDesc = "";
	print "fetching $url ...\n";

	# Allocate and initialize http-request
	$httpRequest = HTTP::Request->new(GET=>$url);
	
	# Initialize user-agent
	$userAgent->timeout(30);
	$userAgent->agent('Mozilla/5.0');
	
	# Send http-request
	$httpResponse = $userAgent->request($httpRequest);
	
	if ($httpResponse->is_success) {
		my $htmlTree = HTML::TreeBuilder->new_from_content($httpResponse->content);
		my @titles = $htmlTree->look_down("_tag","h1","class","title");
		foreach my $title (@titles) {
			$lineName = $title->as_text();
			$lineName =~ s/cattracks\s+-\s+(\w+ (?:\S+ )?Line).*$/$1/i;
		}
		my @mainContents = $htmlTree->look_down("_tag","div","class","content");
		foreach my $content (@mainContents) {
			my $parent = $content->parent();
			my $class = $parent->attr('class');
			next unless (defined($class) and ($class eq "node-inner"));
			my @children = $content->content_list();
			foreach my $child (@children) {
				my $cTag = $child->tag();
				my $cText = $child->as_trimmed_text(extra_chars => '\xA0');
				if ($cTag eq "p") {
					if($cText =~ m/(?:monday through friday|saturday and sunday|saturday midday|friday and saturday)/i) {
						if ($cText =~ m/monday through friday/i) {
							$repeatRule = "1${sep}1${sep}1${sep}1${sep}1${sep}0${sep}0";
						} elsif ($cText =~ m/saturday and sunday/i) {
							$repeatRule = "0${sep}0${sep}0${sep}0${sep}0${sep}1${sep}1";
						} elsif ($cText =~ m/saturday midday/i) {
							$repeatRule = "0${sep}0${sep}0${sep}0${sep}0${sep}1${sep}0";
						} elsif ($cText =~ m/friday and saturday/i) {
							$repeatRule = "0${sep}0${sep}0${sep}0${sep}1${sep}1${sep}0";
						}
					} elsif ($cText =~ m/between/i) {
						$lineDesc = $cText;
						$lineDesc =~ s/^Between/A loop \l$&/;
					}
				} elsif ($cTag eq "table") {
					@stops = ();
					@descs = ();
					@times = ();
					$colNo = -1;
					$rowNo = -1;
					foreach my $descendant ($child->descendants()) {
						next unless (($descendant->tag()) eq "td");
						$departTime = "";
						my $cAttr = $descendant->attr('class');
						my ($hour,$minute);
						$cText = $descendant->as_trimmed_text(extra_chars => '\xA0');
						if ($cAttr eq "text-left smaller") {
							my @locs = $descendant->content_list();
							$stopDesc = "";
							$stopName = "";
							foreach my $loc (@locs) {
								if ($loc =~ m/HTML::Element=HASH/) {
									if (($loc->tag() eq "br") and ($loc->parent()->tag() eq "span")) {
										$stopDesc .= " "
									} elsif ($loc->tag() eq "span") {
										$stopDesc .= $loc->as_text();
									} else {
										$stopName .= $loc->as_text();
									}
								} else {
									$stopName = $loc;
								}
							}
							if ($stopName ne "") {
								push(@stops,$stopName);
								$rowNo++;
								$colNo = -1;
							}
							if ($stopDesc ne "") {
								push(@descs,$stopDesc);
							} else {
								push(@descs,"FIXME ### No stop description given in table. ###");
							}
						} elsif (($cAttr eq "text-right smaller day") or (($cAttr eq "text-right smaller") and ($cText =~ m/\d+:\d+/))) {
							($hour, $minute) = split(/:/,$cText);
							$hour -= 12 if ($hour eq "12");
							$hour = "0" . $hour if ($hour < 10);
							$departTime = "$hour:$minute";
							$colNo++;
						} elsif ($cAttr eq "text-right smaller night") {
							($hour, $minute) = ($1, $2) if $cText =~ m/^\D*(\d+):(\d+)\D*/;
							$hour += 12 unless ($hour eq "12");
							$departTime = "$hour:$minute";
							$colNo++;
						} elsif ((($cAttr eq "text-right smaller day") or ($cAttr eq "text-right smaller") or ($cAttr eq "text-right smaller night")) and ($cText =~ m/--/)) {
							$departTime = "--:--";
							$colNo++;
						}
						next if ($departTime eq "");
						$times[$colNo][$rowNo] = $departTime;
					}
				}
			}
		}
		my $seqNo = 0;
		my $numStops = $#{$times[0]};
		$numStops += 1 if ($lineName =~ m/fastcat/i);
		my $numRuns = $#times + 1;
		for my $i (0..$#times) {
			for my $j (0..$#{$times[$i]}) {
				next if ($times[$i][$j] eq "--:--");
				next if (($j == $#{$times[$i]}) and (($i + 1) <= $#times) and ($stops[$j] eq $stops[0]) and ($times[$i][$j] eq $times[$i + 1][0]));
				push(@lines,"$lineName${sep}$lineDesc${sep}$repeatRule${sep}$stops[$j]${sep}$descs[$j]${sep}$times[$i][$j]${sep}$seqNo${sep}$numStops${sep}$numRuns");
				if ($times[$i][$j] =~ m/0[0-5]:/) {
					my ($h,$m) = split(/:/,$times[$i][$j]);
					$h += 24;
					push(@lines,"$lineName${sep}$lineDesc${sep}$repeatRule${sep}$stops[$j]${sep}$descs[$j]${sep}$h:$m${sep}$seqNo${sep}$numStops${sep}$numRuns");
				}
				$seqNo++;
			}
		}
		$htmlTree = $htmlTree->delete;
	}
	print "done with $url\n";
}
@lines = fixTimes(@lines);

print($writeHandle @lines);
close($writeHandle);

# CatTracks web pages are inconsistent!!!!
sub fixTimes {
	my @pageEntries = @_;
	my @returnEntries = ();
	my ($l_name, $l_desc, $mo, $tu, $we, $th, $fr, $sa, $su, $s_name, $s_desc, $s_time, $s_seq, $numStops, $numRuns);
	my ($l_name1, $l_desc1, $mo1, $tu1, $we1, $th1, $fr1, $sa1, $su1, $s_name1, $s_desc1, $s_time1, $s_seq1, $numStops1, $numRuns1);
	for (my $idx = 1; $idx <= $#pageEntries; $idx++) {
		($l_name, $l_desc, $mo, $tu, $we, $th, $fr, $sa, $su, $s_name, $s_desc, $s_time, $s_seq, $numStops, $numRuns) = split(/\|/,$pageEntries[$idx]);
		($l_name1, $l_desc1, $mo1, $tu1, $we1, $th1, $fr1, $sa1, $su1, $s_name1, $s_desc1, $s_time1, $s_seq1, $numStops1, $numRuns1) = split(/\|/,$pageEntries[$idx - 1]);
		if (($l_name =~ m/^C1/) and ($l_name1 eq $l_name)) {
			if ((substr($s_time,0,2) > 12) and (substr($s_time1,0,2) < 12)) {
				my $tmp = substr($s_time,0,2);
				$tmp -= 12;
				$tmp = "0" . $tmp if ($tmp < 10);
				substr($s_time,0,2,$tmp);
				$pageEntries[$idx] = "$l_name|$l_desc|$mo|$tu|$we|$th|$fr|$sa|$su|$s_name|$s_desc|$s_time|$s_seq|$numStops|$numRuns";
			}
		} elsif (($l_name =~ m/^E /) and ($l_name1 eq $l_name)) {
			if ((substr($s_time,0,2) == 12) and ((substr($s_time1,0,2) > 12) or (substr($s_time1,0,2) == 0))) {
				my $tmp = substr($s_time,0,2);
				$tmp -= 12;
				$tmp = "0" . $tmp if ($tmp < 10);
				substr($s_time,0,2,$tmp);
				$pageEntries[$idx] = "$l_name|$l_desc|$mo|$tu|$we|$th|$fr|$sa|$su|$s_name|$s_desc|$s_time|$s_seq|$numStops|$numRuns";
			}
		}
		push(@returnEntries,"$l_name1|$l_desc1|$mo1|$tu1|$we1|$th1|$fr1|$sa1|$su1|$s_name1|$s_desc1|$s_time1|$s_seq1|$numStops1|$numRuns1\n") if ($idx - 1 == 0);
		push(@returnEntries,"$l_name|$l_desc|$mo|$tu|$we|$th|$fr|$sa|$su|$s_name|$s_desc|$s_time|$s_seq|$numStops|$numRuns\n");
	}
	return (@returnEntries);
}

__END__
